using System;
using System.Collections.Generic;
using System.Text.Json;
using System.Threading.Tasks;
using Microsoft.Extensions.Caching.Distributed;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Volo.Abp.DependencyInjection;
using Matrix.Configuration.DTOs;

namespace Matrix.Configuration.Configuration
{
    /// <summary>
    /// 智能配置缓存管理器
    /// 实现L1内存缓存 + L2分布式缓存的多层缓存架构
    /// </summary>
    public class SmartConfigurationCacheManager : ITransientDependency
    {
        private readonly IMemoryCache _memoryCache;
        private readonly IDistributedCache _distributedCache;
        private readonly ILogger<SmartConfigurationCacheManager> _logger;
        private readonly IOptions<SmartConfigurationCacheOptions> _options;

        // L1缓存配置
        private readonly TimeSpan _memoryCacheTtl;
        private readonly int _memoryCacheMaxSize;

        // L2缓存配置
        private readonly TimeSpan _distributedCacheTtl;

        public SmartConfigurationCacheManager(
            IMemoryCache memoryCache,
            IDistributedCache distributedCache,
            ILogger<SmartConfigurationCacheManager> logger,
            IOptions<SmartConfigurationCacheOptions> options)
        {
            _memoryCache = memoryCache;
            _distributedCache = distributedCache;
            _logger = logger;
            _options = options;

            var cacheOptions = _options.Value;
            _memoryCacheTtl = cacheOptions.MemoryCacheTtl;
            _memoryCacheMaxSize = cacheOptions.MemoryCacheMaxSize;
            _distributedCacheTtl = cacheOptions.DistributedCacheTtl;
        }

        /// <summary>
        /// 获取缓存配置项
        /// </summary>
        /// <param name="key">缓存键</param>
        /// <returns>配置项DTO，如果不存在则返回null</returns>
        public async Task<ConfigurationItemDto?> GetAsync(string key)
        {
            // L1缓存查找
            if (_memoryCache.TryGetValue(key, out ConfigurationItemDto? cachedValue))
            {
                _logger.LogDebug("L1缓存命中: {Key}", key);
                return cachedValue;
            }

            // L2缓存查找
            var distributedValue = await _distributedCache.GetStringAsync(key);
            if (distributedValue != null)
            {
                _logger.LogDebug("L2缓存命中: {Key}", key);

                try
                {
                    var configItem = JsonSerializer.Deserialize<ConfigurationItemDto>(distributedValue);
                    if (configItem != null)
                    {
                        // 更新L1缓存
                        SetMemoryCache(key, configItem);
                        return configItem;
                    }
                }
                catch (JsonException ex)
                {
                    _logger.LogError(ex, "反序列化分布式缓存数据失败: {Key}", key);
                    // 反序列化失败，删除损坏的缓存
                    await _distributedCache.RemoveAsync(key);
                }
            }

            _logger.LogDebug("缓存未命中: {Key}", key);
            return null;
        }

        /// <summary>
        /// 设置缓存配置项
        /// </summary>
        /// <param name="key">缓存键</param>
        /// <param name="value">配置项DTO</param>
        public async Task SetAsync(string key, ConfigurationItemDto value)
        {
            if (value == null)
            {
                _logger.LogWarning("尝试设置null值到缓存: {Key}", key);
                return;
            }

            // 设置L1缓存
            SetMemoryCache(key, value);

            // 设置L2缓存
            try
            {
                var serializedValue = JsonSerializer.Serialize(value);
                await _distributedCache.SetStringAsync(
                    key,
                    serializedValue,
                    new DistributedCacheEntryOptions
                    {
                        AbsoluteExpirationRelativeToNow = _distributedCacheTtl
                    });
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "设置分布式缓存失败: {Key}", key);
                // L1缓存设置成功，但L2失败，记录日志但不抛出异常
            }

            _logger.LogDebug("缓存设置成功: {Key}", key);
        }

        /// <summary>
        /// 删除缓存配置项
        /// </summary>
        /// <param name="key">缓存键</param>
        public async Task RemoveAsync(string key)
        {
            _memoryCache.Remove(key);
            await _distributedCache.RemoveAsync(key);
            _logger.LogDebug("缓存删除成功: {Key}", key);
        }

        /// <summary>
        /// 批量删除缓存
        /// </summary>
        /// <param name="keys">缓存键集合</param>
        public async Task RemoveBatchAsync(IEnumerable<string> keys)
        {
            var keysList = keys?.ToList() ?? new List<string>();

            if (!keysList.Any())
            {
                return;
            }

            // 并行删除L1缓存
            foreach (var key in keysList)
            {
                _memoryCache.Remove(key);
            }

            // 并行删除L2缓存
            var tasks = keysList.Select(key => _distributedCache.RemoveAsync(key));
            await Task.WhenAll(tasks);

            _logger.LogDebug("批量删除缓存成功，数量: {Count}", keysList.Count);
        }

        /// <summary>
        /// 检查缓存是否存在
        /// </summary>
        /// <param name="key">缓存键</param>
        /// <returns>是否存在</returns>
        public async Task<bool> ExistsAsync(string key)
        {
            // 先检查L1缓存
            if (_memoryCache.TryGetValue(key, out _))
            {
                return true;
            }

            // 检查L2缓存
            var value = await _distributedCache.GetStringAsync(key);
            return !string.IsNullOrEmpty(value);
        }

        /// <summary>
        /// 刷新L1缓存（从L2缓存重新加载）
        /// </summary>
        /// <param name="key">缓存键</param>
        public async Task RefreshAsync(string key)
        {
            // 删除L1缓存，强制下次从L2缓存重新加载
            _memoryCache.Remove(key);
            _logger.LogDebug("L1缓存刷新成功: {Key}", key);
        }

        /// <summary>
        /// 清空所有缓存
        /// </summary>
        public async Task ClearAsync()
        {
            // 清空L1缓存
            if (_memoryCache is MemoryCache memoryCache)
            {
                memoryCache.Compact(1.0); // 压缩内存缓存，删除所有过期项
            }

            // 注意：无法清空所有L2缓存，只能通过其他机制实现
            _logger.LogInformation("L1缓存清空完成");
        }

        /// <summary>
        /// 获取缓存统计信息
        /// </summary>
        /// <returns>缓存统计信息</returns>
        public ConfigurationCacheStatistics GetStatistics()
        {
            // 注意：IMemoryCache接口不直接提供统计信息
            // 这里返回基础信息，实际项目中可能需要使用自定义实现
            return new ConfigurationCacheStatistics
            {
                MemoryCacheEntries = GetMemoryCacheCount(),
                MemoryCacheSize = EstimateMemoryCacheSize(),
                DistributedCacheEnabled = _distributedCache != null
            };
        }

        private void SetMemoryCache(string key, ConfigurationItemDto value)
        {
            var options = new MemoryCacheEntryOptions
            {
                AbsoluteExpirationRelativeToNow = _memoryCacheTtl,
                Size = 1, // 用于大小管理
                Priority = CacheItemPriority.Normal
            };

            // 设置缓存过期回调
            options.PostEvictionCallbacks.Add(new PostEvictionCallbackRegistration
            {
                EvictionCallback = OnCacheEviction,
                State = key
            });

            _memoryCache.Set(key, value, options);
        }

        private void OnCacheEviction(object key, object value, EvictionReason reason, object state)
        {
            _logger.LogDebug("L1缓存过期: {Key}, 原因: {Reason}", key, reason);
        }

        private int GetMemoryCacheCount()
        {
            // 这是一个估算值，实际实现中可能需要使用自定义缓存实现
            return 0;
        }

        private long EstimateMemoryCacheSize()
        {
            // 这是一个估算值，单位：字节
            return _memoryCacheMaxSize * 1024; // 假设每个条目平均1KB
        }
    }

    /// <summary>
    /// 智能缓存配置选项
    /// </summary>
    public class SmartConfigurationCacheOptions
    {
        /// <summary>
        /// 内存缓存TTL，默认30分钟
        /// </summary>
        public TimeSpan MemoryCacheTtl { get; set; } = TimeSpan.FromMinutes(30);

        /// <summary>
        /// 内存缓存最大条目数，默认1000
        /// </summary>
        public int MemoryCacheMaxSize { get; set; } = 1000;

        /// <summary>
        /// 分布式缓存TTL，默认2小时
        /// </summary>
        public TimeSpan DistributedCacheTtl { get; set; } = TimeSpan.FromHours(2);

        /// <summary>
        /// 是否启用缓存压缩，默认false
        /// </summary>
        public bool EnableCompression { get; set; } = false;

        /// <summary>
        /// 缓存键前缀，默认为空
        /// </summary>
        public string KeyPrefix { get; set; } = string.Empty;
    }

    /// <summary>
    /// 配置缓存统计信息
    /// </summary>
    public class ConfigurationCacheStatistics
    {
        /// <summary>
        /// 内存缓存条目数
        /// </summary>
        public int MemoryCacheEntries { get; set; }

        /// <summary>
        /// 内存缓存大小（字节）
        /// </summary>
        public long MemoryCacheSize { get; set; }

        /// <summary>
        /// 分布式缓存是否启用
        /// </summary>
        public bool DistributedCacheEnabled { get; set; }

        /// <summary>
        /// 最后更新时间
        /// </summary>
        public DateTime LastUpdated { get; set; } = DateTime.UtcNow;
    }
}